using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using System.Xml;

namespace Microsoft.SharedSource.SqlServer.MDDE.Components
{
    [
        System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased"),
        SupportedComponentType("{C3BF9DC1-4715-4694-936F-D3CFDA9E42C5}"),
        SupportedComponentType("DTS.Pipeline.1")
    ]
    public sealed class MDDEDataFlowTask:MDDETask
    {
        #region Member Variables

        private MDDEExecutionDAG innerExecutionDAG;

        private XmlNodeList changedProperties = null;
        private TaskHost component = null;

        #endregion

        public MDDEDataFlowTask(Package package, Object component, string name, string uri)
            : base(package, component, name, uri)
        {
            if (!((component is TaskHost) && ((component as TaskHost).InnerObject is MainPipe)))
                throw new ArgumentException();

            this.innerExecutionDAG = new MDDEExecutionDAG(this.package, this, (component as TaskHost), uri);
        }

        #region Overridden Methods

        public override MDDEComponent GetChildComponent(string uri)
        {
            if (null == this.innerExecutionDAG)
                return null;
            return innerExecutionDAG.GetMDDEComponentByUri(uri);
        }

        public override bool CompareTo(MDDEComponent subject, bool deepCompare)
        {
            if (!(subject is MDDEDataFlowTask))
                return false;

            if (this.Name != subject.Name)
                return false;

            if (deepCompare && !this.innerExecutionDAG.CompareTo((subject as MDDEDataFlowTask).innerExecutionDAG, true))
                return false;

            return true;
        }

        public override void GetDifference(MDDEComponent subject, System.Xml.XmlDocument differenceReport)
        {
            if (null == subject)
            {
                this.innerExecutionDAG.GetDifference(null, differenceReport);
            }
            else
            {
                if (!(subject is MDDEDataFlowTask))
                    throw new ArgumentException();
                this.innerExecutionDAG.GetDifference((subject as MDDEDataFlowTask).innerExecutionDAG, differenceReport);
            }
        }

        public override void GetChangeXml(MDDEComponent subject, XmlDocument changeXml)
        {
            #region Verify subject

            if (subject == null)
                throw new ArgumentNullException("Subject can not NULL");

            if (!(subject is MDDEDataFlowTask))
                throw new ArgumentException("Subject is not of type MDDEDataFlowTask");

            #endregion

            #region Call Base Method

            base.GetChangeXml(subject, changeXml);

            #endregion
        }

        public override bool ApplyChanges(System.Xml.XmlDocument changeXml, MDDEExecutionDAG originalPackage)
        {
            return base.ApplyChanges(changeXml, originalPackage);
        }

        public override XmlDocument GetComponentTree()
        {
            // Create a tree document.
            XmlDocument componentTree = base.GetComponentTree();

            // Clear off the attributes on Root node.
            XmlElement xRoot = componentTree.DocumentElement;
            xRoot.Attributes.RemoveAll();

            // Add in fresh attributes.
            AppendAttribute(xRoot,
                new string[]{"Type", "Executable", "Name", Name, "Uri", Uri,
                    "ClassId", "DTS.Pipeline.1", "RowsetDescriptorType", string.Empty,
                    "ContainsMappings", "False", "ContainsCollections", "False" });

            // Add the 'Components' node.
            XmlElement xComponents = AppendChildElement(componentTree.DocumentElement, "Node",
                new string[]{"Type", "Collection","Name", "Components","Uri", Uri + "/Components",
                    "ClassId", string.Empty,"RowsetDescriptorType", string.Empty,
                    "ContainsMappings", "False", "ContainsCollections", "False" });

            // Traverse the execution DAG in execution order.
            foreach (MDDEComponent graphNode in this.innerExecutionDAG)
            {
                // Append the successor tree to appropriate parent node.

                // Check for Components.
                if (graphNode is MDDEDataFlowComponent)
                {
                    // Get the component tree of node.
                    XmlDocument xSuccessorTree = graphNode.GetComponentTree();

                    if (xSuccessorTree == null)
                        continue;

                    // Append the child tree to 'Components' node.
                    xComponents.AppendChild(
                        componentTree.ImportNode(
                        xSuccessorTree.DocumentElement, true));
                }
            }

            return componentTree;
        }

        #endregion
    }
}
